//------------------------------------------------------------------------------
// Fichiers d'ent�te utilises
//------------------------------------------------------------------------------ 
#include "IsoDataThresholdFinder.hpp" 
#include "Tools/Logger.hpp"

namespace ImageAnalysis
{

	//------------------------------------------------------------------------------
	// 
	//------------------------------------------------------------------------------ 
	IsoDataThresholdFinder::IsoDataThresholdFinder():
	ThresholdFinder()
	{
	
	}
	
	//------------------------------------------------------------------------------
	// 
	//------------------------------------------------------------------------------ 
	IsoDataThresholdFinder::~IsoDataThresholdFinder()
	{
	
	}
	
	//------------------------------------------------------------------------------
	// 
	//------------------------------------------------------------------------------ 
	unsigned char * IsoDataThresholdFinder::GetOneThreshold(Region* regionToStudy, Gradiant* gradiantToStudy)
	{
		//Récupération de l'histogramme de la région du gradiant
		Histogram * histogram = gradiantToStudy->GetHistogram(regionToStudy);
	
		// On cherche les bornes non nulles de l'histogramme
		int min = -1;
		int max = -1;
		int i=0;
		while( i<=255 && min == -1)
		{
			if(histogram->GetNumberOfPixel(i) !=0 )
			{
				min = i;
			}
			i++;
		}
	
		i=255;
		while( i >= 0 && max == -1)
		{
			if(histogram->GetNumberOfPixel(i) != 0)
			{
				max = i;
			}
			i--;
		}
			
		Tools::ILogger::Log("min: %d, max: %d \n", min, max);
		
		
		
		unsigned char * threshold = new unsigned char [1];
		if( min != max )
		{
			threshold[0] = (unsigned char)ComputeThreshold(min,max,histogram);
		
			Tools::ILogger::Log("Thres: %d \n", threshold[0]);
			delete histogram;
		}
		else
		{	
			threshold[0] = 255;
		}

		return threshold;
	}
	
	//------------------------------------------------------------------------------
	// 
	//------------------------------------------------------------------------------
	unsigned char * IsoDataThresholdFinder::GetTwoThresholds(Region* regionToStudy, Gradiant* gradiantToStudy)
	{
		//Récupération de l'histogramme de la région du gradiant
		Histogram * histogram = gradiantToStudy->GetHistogram(regionToStudy);
	
		//On cherche les bornes non nulles de l'histogramme
		int min = -1;
		int max = -1;
		int i=0;
		while( i<=255 && min == -1)
		{
			if(histogram->GetNumberOfPixel(i) !=0 )
			{
				min = i;
			}
			i++;
		}
	
		i=255;
		while( i >= 0 && max == -1)
		{
			if(histogram->GetNumberOfPixel(i) != 0)
			{
				max = i;
			}
			i--;
		}
	
		//On fait un calcul normal du seuil par isodata pour déterminer la frontière entre deux classes
		unsigned char* middle = GetOneThreshold(regionToStudy,gradiantToStudy);
	
		//Maintenant, on va calculer un seuil dans la classe à gauche de middle et un à droite de middle
		//cela revient à calculer deux fois isodata sur ces deux parties de l'histogramme
	
		//partie gauche
		int leftThreshold = ComputeThreshold(min,*middle,histogram);
	
		//partie droite
		int rightThreshold = ComputeThreshold(*middle+1,max,histogram);
	
		unsigned char * thresholds = new unsigned char [2];
		thresholds[0] = (unsigned char)leftThreshold;
		thresholds[1] = (unsigned char)rightThreshold;
		
		Tools::ILogger::Log("ISO::Thres1: %d, ISO::Thres2: %d \n", thresholds[0], thresholds[1]);
		delete[] middle;
		delete histogram;

		return thresholds;
	}
	
	//------------------------------------------------------------------------------
	// 
	//------------------------------------------------------------------------------
	int IsoDataThresholdFinder::ComputeThreshold(int borneInf, int borneSup, Histogram* histogram)
	{
		int average = (borneInf+borneSup)/2;
	
		bool loop = true;
		int m1 =0;
		int m2 =0;
		int T = 0;
		while(loop)
		{
			m1 = ComputeAvgClass(borneInf,average,histogram);
			m2 = ComputeAvgClass(average+1,borneSup,histogram);
			T = (m1+m2)/2;
			if(T==average)
				loop=false;
			else
				average = T;
			
		}
	
		return average;
	}

	//------------------------------------------------------------------------------
	// 
	//------------------------------------------------------------------------------
	int IsoDataThresholdFinder::ComputeAvgClass(int borneInf, int borneSup, Histogram* histogram)
	{
		int Div = 0;
		int Val = 0;
		for( int i=borneInf;i<=borneSup;i++)
		{
			Val += i*histogram->GetNumberOfPixel(i);
			Div += histogram->GetNumberOfPixel(i);
		}
		return (Val/Div);
	}
}

